#ifndef _DATA_STRUCTURE_H_
#define _DATA_STRUCTURE_H_


#include "btree.h"
#include "time.h"
#include "template_list.h"
#include "utility.h"
#pragma warning(disable:4996)

// The different data of the database
typedef union data_t
{
	int int_data;

	char* p_char_data;

	float float_data;
	
}data_t;

// The key
typedef struct key_t{

	enum data_type_t type;

	union data_t data;

} atom_data;

DEFINE_LIST(data_t);

// The tuple
typedef struct tuple_t
{
	int index;

	DECLARE_LIST(data_t) data_list;

}tuple_t;
DEFINE_LIST(tuple_t);
DEFINE_POINTER_LIST(tuple_t);

typedef struct 
{
	char elem[MAX_NAME_LENGTH_P1];
}str;
DEFINE_LIST(str);

// a list composed of the columns of a table\
// Revised: BBzjdrk at 2010-5-21
//	Add the default data to a column
//  Change the 'is_key' property to the table struct
typedef struct column
{	
	// the data_type of the column
	data_type_t type;

	// the size of the data
	int i_column_size;

	// the name of the column
	char column_name[MAX_NAME_LENGTH_P1];

	// if it is allowed to be null
	BOOL_EX allow_null;

	// the default value of this column
	atom_data d_defualt_value;

	// is key
	BOOL_EX is_one_of_key;

}column;
// Define a list of "column" struct 
DEFINE_LIST(column);
DEFINE_POINTER_LIST(column);


// The btree 
typedef struct btree_t
{
	/* number of keys */
	int num; 
	/* if or not is a leaf */
	char leaf;
	/*The actual data, tuples*/
	tuple_t* tuple_array[KEY_NUM];
	/*The child braches*/
	struct btree_t* child_array[KEY_NUM + 1];

}btree_t, btnode_t;

DEFINE_LIST(int);

typedef struct table
{
	// table name
	char name[MAX_NAME_LENGTH_P1];
	// create time of the table
	time_t create_time;
	// the count of tuples
	int tuple_count;

	// the property of the columns
	DECLARE_POINTER_LIST(column) pcolumn_property_list;

	//// index
	//list* indexes;

	// The current key index, to maintain the btree's key.
	int i_current_max_index;
	
	// the actual data
	struct btree_t* root;

	// the primary key of this table, column indexed  of the table's keys are perseved.

	DECLARE_LIST(int) primary_key;
		
	/*Obsolete*/
	// The compare function of the table used to compare 
	//int (*compare)(struct tuple_t* left, struct tuple_t* right);
}table;
// A list of tables
DEFINE_LIST(table);
DEFINE_POINTER_LIST(table);


typedef struct database
{

	// the create time
	time_t create_time;

	// the name of the database
	char p_db_name[MAX_NAME_LENGTH_P1];

	/*??????????????????????????????????????????????????????????????????????*/
	// The size is specified at the beginning, so it's a problem to control the data size
	int p_db_size;
	/*??????????????????????????????????????????????????????????????????????*/
	
	// the tables of the db
	DECLARE_POINTER_LIST(table) ptable_list;

	// The user of the database, only one is allowed
	char p_db_user[MAX_USER_PWD_LENGTH_P1];
	
	// The password of the user, for security reasons
	// If we should add some encoding technique ????
	char p_db_password[MAX_USER_PWD_LENGTH_P1];
	
	// the log file path 
	char p_log_file_path[MAX_PATH_LENGTH_P1];
	
	// the db file path
	char p_db_file_path[MAX_PATH_LENGTH_P1];

	// the file pointer of db, 
	// Attention: used after you open the file
	FILE* p_db_file;

	// Attention: used after you open the file
	// the file pointer of log 
	FILE* p_log_file;

}database;
DEFINE_LIST(database);
DEFINE_POINTER_LIST(database);


typedef enum 
{
	GREATER,
	SMALLER,
	EQUAL
}compare_operator;

typedef enum 
{
	AND,
	OR

}compare_type;


// The condition for the searching, updating and deleting 
typedef struct
{
	// the compare operator >, <, =
	compare_operator* com_operator;
	// the compare type "and" or "or"
	compare_type com_type;
	// the count of columns this condition will take effect
	int i_condition_count;
	// the actual data which the compare function will use
	void** pp_data_array;
	// the column_index
	int* p_column_index_array;


}condition, raw_value;

// the application 
typedef struct MMDB
{
	// the time when the database started
	time_t startup_time;
	// the current databases
	DECLARE_POINTER_LIST(database) pdatabase_list;
	// the count of alive database
	int i_cur_alive;

	// maximum connection count
	int i_max_conn_count;
	// current connection count
	int i_cur_conn_count;

	char config_file[MAX_PATH_LENGTH_P1];

	// the name of the dba
	char p_dba_name[MAX_USER_PWD_LENGTH_P1];
	// the pwd of the dba
	char p_dba_pwd[MAX_USER_PWD_LENGTH_P1];

}MMDB;	

typedef struct
{
	table* pc_table;
	DECLARE_POINTER_LIST(column) column_list;
	DECLARE_LIST(int) column_index_list;
	DECLARE_POINTER_LIST(tuple_t) tuple_result_list;
}DataSet;


int compare_index(struct tuple_t* left, struct tuple_t* right );

#endif /*_DATA_STRUCTURE_H_*/